﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Ionic.Utils;

using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
using SaveFileDialog = Microsoft.Win32.SaveFileDialog;

namespace Elca.MvvmHelpers.Services {

    public class BrowseFileSystem : IBrowseFileSystem {

        /// <summary>
        /// Asks the user for a file name where data can be saved.
        /// </summary>
        /// <param name="title">Title of the save file dialog</param>
        /// <param name="path">If the user confirms the request, the path is returned here</param>
        /// <param name="fileType">The file type description, in the current language</param>
        /// <param name="extension">The default extension of the file</param>
        /// <param name="defaultPath">Path where the file browser should be open</param>
        /// <returns>True if the user confirms the request, false otherwise</returns>
        public bool AskForFileToSave(string title, string fileType, string extension, string defaultPath, out string path) {

            path = null;
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.CheckPathExists = false;
            sfd.Title = title;
            sfd.Filter = MakeFilter(fileType, extension);
            sfd.InitialDirectory = GetClosestDirectory(defaultPath);
            if (sfd.ShowDialog() == true) {
                path = sfd.FileName;
            }

            return path != null;
        }

        /// <summary>
        /// Asks the user for an existing file name where data can be read from.
        /// </summary>
        /// <param name="title">Title of the open file dialog</param>
        /// <param name="path">If the user confirms the request, the path is returned here</param>
        /// <param name="fileType">The file type description, in the current language</param>
        /// <param name="defaultPath">Path where the file browser should be open</param>
        /// <param name="extension">The default extension of the file</param>
        /// <returns>True if the user confirms the request, false otherwise</returns>
        public bool AskForFileToOpen(string title, string fileType, string extension, string defaultPath, out string path) {

            path = null;
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.CheckFileExists = true;
            ofd.Title = title;
            ofd.Multiselect = false;
            ofd.Filter = MakeFilter(fileType, extension);
            ofd.InitialDirectory = GetClosestDirectory(defaultPath);

            if (ofd.ShowDialog() == true) {
                path = ofd.FileName;
            }
            return path != null;
        }

        /// <summary>
        /// Asks the user for an existing file name where data can be read from.
        /// </summary>
        /// <param name="title">Title of the open file dialog</param>
        /// <param name="path">If the user confirms the request, the path is returned here</param>
        /// <param name="defaultPath">Path where the file browser should be open</param>
        /// <returns>True if the user confirms the request, false otherwise</returns>
        public bool AskForDirectory(string title, string defaultPath, out string path) {

            path = null;

            var dlg1 = new FolderBrowserDialogEx
            {
                Description = "Select a folder for the extracted files:",
                ShowNewFolderButton = false,
                ShowEditBox = true,
                SelectedPath = GetClosestDirectory(defaultPath),
                NewStyle = false,
                ShowFullPathInEditBox= true,
            };
             
            var result = dlg1.ShowDialog();
             
            if (result == DialogResult.OK)
            {
                path = dlg1.SelectedPath;
            }

            return path != null;
        }

        private static string MakeFilter(string fileType, string extension) {
            return String.Format("{0} (*.{1})|*.{1}|{2} (*.*)|*.*", fileType, extension, "All files");
        }

        private string GetClosestDirectory(string initialPath) {
            
            if (String.IsNullOrEmpty(initialPath)) {
                return Environment.CurrentDirectory;
            }

            while (true) {
                
                if (Directory.Exists(initialPath)) {
                    return initialPath;
                }

                int index = initialPath.LastIndexOf('\\');

                if (index == -1) {
                    // no more \
                    return Environment.CurrentDirectory;
                }

                initialPath = initialPath.Substring(0, index);
            }
        }
    }
}
